////////////////////////////////////////////////////////////////////////////////
/*!	\file		testC45.cpp
**	\brief		Defines all functionality in testC45.hpp.
**	\author		Nate Cleveland
**	\date		2/7/2003 2:04:52 PM
**	\par		DESCRIPTION:
**					See testC45.hpp for details.
**	\par		REMARKS:
**					
*/
////////////////////////////////////////////////////////////////////////////////
#include "../dTrees/C45Generator.hpp"
#include "../dTrees/treeFileIO.hpp"
#include "testC45.hpp"
#include <fstream>
#include <memory.h>
#include <stdio.h>
#include <assert.h>
using namespace DTree;

//See Header for documentation.
TestC45::TestC45()
:m_root(NULL)
{
	
	
}

//See Header for documentation.
TestC45::~TestC45()
{
	if(m_root) 
		delete m_root;

	m_exampleVec.clear();
}

//See Header for documentation.
TestC45::TestC45(const TestC45& toCopyFrom) throw()
:m_root(NULL)
{
	//don't bother copying if we don't have any data.
	if(toCopyFrom.m_root)
	{
		//allocate a new node for the tree.
		m_root = new TestNode;
		
		//Do a deep copy of our tree.
		TestNode::DeepCopy(*(toCopyFrom.m_root), *(this->m_root));
	}
}


//See Header for documentation.
bool TestC45::save(const char *pathName) throw()
{
	if(!pathName)
		return false;

	std::ofstream hFile(pathName);

	try{
		TreeFileIO<TestC45::TestNode> treeIO(m_root, hFile);
	} catch(...)
	{
		return false;
	}

	return true;
}

//See Header for documentation.
bool TestC45::load(const char *pathName) throw()
{
	if(!pathName)
		return false;

	std::ifstream hFile(pathName);


	try{
		TreeFileIO<TestC45::TestNode> treeIO(m_root, hFile);
	} catch(...)
	{
		return false;
	}
	
	return true;
}

//See Header for documentation.
bool TestC45::Think(std::vector<float> caseVec)
{	
	//If we don't have any nodes yet just return true to all queryies.
	if(!m_root)
		return true;	

	//Recursively treverse the tree. See nodes.hpp for more details.
	return (*m_root)(caseVec);
}

//See Header for documentation.
void TestC45::GiveExample(std::vector<float> caseVec, bool result)
{
	//create a new example
	TestExample testEx;

	testEx.m_caseVec = caseVec;
	testEx.m_result = result;

	//assert that its size is correct. ie non-zero and same as all others.
	assert(caseVec.size());

	if(m_exampleVec.size())
		assert(testEx.m_caseVec.size() == m_exampleVec.back().m_caseVec.size());

	//add to example vector.
	m_exampleVec.push_back(testEx);
}

//See Header for documentation.
void TestC45::Learn(void) throw()
{
	//must have at lease 1 example
	if(m_exampleVec.size())
	{
		
		std::vector<bool> classVec;
		classVec.push_back(false);
		classVec.push_back(true);
		
		try
		{
			C45Generator<TestC45, TestC45::AIUnitAdapter, TestC45::AIUnitAdapter::Node_type, TestC45::AIUnitAdapter::Case_type, TestC45::AIUnitAdapter::Class_type, TestC45::AIUnitAdapter::Example_type> c45(*this, classVec);
			c45();
			m_exampleVec.clear();	//Clear out all used examples.
		} catch(char* str)
		{
			std::cout << str << std::endl;
		} catch(...)
		{
			if(m_root)
				delete m_root;
		}// try\catch block
	}//if
}//Learn
